home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Languages / CW MacMindy 1.4 / Examples / QD3D-Viewer / QD3D-Viewer Sources / QD3ViewerMain.dyl < prev   
Encoding:
Text File  |  1995-11-17  |  12.2 KB  |  451 lines  |  [TEXT/CWIE]

  1. module:    Main
  2.  
  3. /*
  4.     QD3ViewerMain.dyl
  5.  
  6.     QD3D Application example for Mindy Dylan.
  7.     
  8.     This demonstrates direct use of the Toolbox from Dylan.
  9.     It is not a good example of how Dylan SHOULD be used.    
  10.     
  11.     by Patrick C. Beard.
  12.  */
  13.  
  14. define library QD3D-Example
  15.     use dylan;
  16.     use format;
  17.     use Toolbox;
  18.     use QD3D;
  19. end library QD3D-Example;
  20.  
  21. define module Main
  22.     use dylan;
  23.     use extensions, import: { main, <equal-table>, <boolean> };
  24.     use threads;                            // imports "spawn-thread".
  25.     use extern;                                // imports "<c-string>".
  26.     use format, import: { format-to-string };
  27.     use Toolbox;                            // imports "Debugger", etc.
  28.     
  29.     use QD3DTypes;
  30.     use QD3DMath;
  31.     use QD3DMisc;
  32.     use QD3DViewer;
  33. end module Main;
  34.  
  35. // menu constants.
  36.  
  37. define constant $MenuBar-ID =128;
  38.  
  39. define constant $Apple-Menu-ID = 128;
  40. define constant $About-Item = 1;
  41.  
  42. define constant $File-Menu-ID = 129;
  43. define constant $New-Item = 1;
  44. define constant $Open-Item = 2;
  45. define constant $Close-Item = 3;
  46. define constant $Quit-Item = 5;
  47.  
  48. define constant $Edit-Menu-ID = 130;
  49. define constant $Undo-Item = 1;
  50. define constant $Cut-Item = 3;
  51. define constant $Copy-Item = 4;
  52. define constant $Paste-Item = 5;
  53. define constant $Clear-Item = 6;
  54.  
  55. define constant $Font-Menu-ID = 131;
  56.  
  57. // alert & dialog constants.
  58.  
  59. define constant $About-Alert-ID = 128;
  60. define constant $Document-Window-ID = 128;
  61. define constant $Cricket-snd-ID = 128;
  62.  
  63. // main!
  64.  
  65. define method main (argv0, #rest args)
  66.     let menuBar = GetNewMBar($MenuBar-ID);
  67.     if (menuBar ~= $nil)
  68.         SetMenuBar(menuBar);
  69.         FillMenu($Apple-Menu-ID, "DRVR");
  70.         FillMenu($Font-Menu-ID, "FONT");
  71.         DrawMenuBar();
  72.         EventLoop();
  73.     end if;
  74. end method main;
  75.  
  76. define method FillMenu(menuID :: <integer>, typestr :: <string>)
  77.     let menu = GetMenuHandle(menuID);
  78.     if (menu ~= $nil)
  79.         AppendResMenu(menu, os-type(typestr));
  80.     end if;
  81. end method FillMenu;
  82.  
  83. // get access to a C global that gets set when a "Quit" AppleEvent is received.
  84. define constant theTimeToQuit = find-c-pointer("theTimeToQuit");
  85. define constant collect-garbage = get-c-function("collect_garbage", args: #(), result: #());
  86. define constant $min-free-mem = 512 * 1024;
  87. define constant $untitled-name = as(<Pascal-string>, "Untitled Viewer");
  88.  
  89. define method garbage-collector ()
  90.     let cursor-handle = GetCursor(128);
  91.     if (cursor-handle ~= $nil)
  92.         HLockHi(cursor-handle);
  93.         let cursor-ptr = pointer-at(cursor-handle);
  94.         while (#t)
  95.             if (FreeMem() < $min-free-mem)
  96.                 SetCursor(cursor-ptr);
  97.                 collect-garbage();
  98.                 SetCursor(qd.arrow);
  99.             end if;
  100.         end while;
  101.     end if;
  102. end method garbage-collector;
  103.  
  104. // create some support for dealing with QD3D matrices.
  105.  
  106. define method make (class == <TQ3Matrix4x4>, #all-keys)
  107.     as(<TQ3Matrix4x4>, NewPtr(content-size(<TQ3Matrix4x4>)));
  108. end method make;
  109.  
  110. define method destroy (obj :: <TQ3Matrix4x4>) => ();
  111.     DisposePtr(as(<Ptr>, obj));
  112. end method destroy;
  113.  
  114. define class <Viewer-Document> (<object>)
  115.     slot viewer-window :: <WindowPtr>, init-keyword: window:;
  116.     slot viewer-object :: <TQ3ViewerObject>, init-keyword: viewer:;
  117.     slot viewer-matrix :: <TQ3Matrix4x4>;
  118. end class <Viewer-Document>;
  119.  
  120. define method initialize (self :: <Viewer-Document>, #next next-method, #key window, viewer)
  121.     next-method();
  122.     self.viewer-matrix := make(<TQ3Matrix4x4>);
  123.     Q3Matrix4x4-SetIdentity(self.viewer-matrix);
  124. end method initialize;
  125.  
  126. define method EventLoop () => ();
  127.     // some variables we'll need.
  128.     let event = make(<EventRecord>);
  129.     let localWhere = point(0, 0);
  130.     let itemString = make (<Pascal-string>);
  131.     let mouseRgn = NewRgn();
  132.     let oldClip = NewRgn();
  133.     let newClip = NewRgn();
  134.     RectRgn(mouseRgn, qd.screenBits.bounds);
  135.     let textRect = make(<Rect>, bottom: 32, right: 100);
  136.     let sizeRect = make(<Rect>, top: 100, left: 100, bottom: 1000, right: 1000);
  137.     let viewer-documents = make(<equal-table>);
  138.     let reply = make(<StandardFileReply>);
  139.     let tempMatrix = make(<TQ3Matrix4x4>);
  140.     
  141.     /* let collector-thread = spawn-thread("garbage-collector", garbage-collector); */
  142.     
  143.     block (return)
  144.         local method FrontDocument () => (window, viewer, document);
  145.             let frontWindow = FrontWindow();
  146.             let frontDoc = element(viewer-documents, frontWindow, default: #f);
  147.             let frontViewer =
  148.                 if (frontDoc)
  149.                     frontDoc.viewer-object;
  150.                 else
  151.                     $nil;
  152.                 end if;
  153.             values(frontWindow, frontViewer, frontDoc);
  154.         end method;
  155.         
  156.         local method DrawClippedGrowIcon (window :: <WindowPtr>)
  157.             GetClip(oldClip);
  158.             let r = window.portRect;
  159.             SetRectRgn(newClip, r.right - 15, r.bottom - 15, r.right, r.bottom);
  160.             SetClip(newClip);
  161.             DrawGrowIcon(window);
  162.             SetClip(oldClip);
  163.         end method;
  164.     
  165.         // draw window here.
  166.         local method DrawViewer (window :: <WindowPtr>)
  167.             SetPort(window);
  168.             Q3ViewerDraw(viewer-documents[window].viewer-object);
  169.             DrawClippedGrowIcon(window);
  170.         end method;
  171.         
  172.         local method NewViewer ()
  173.             let window = GetNewCWindow($Document-Window-ID);
  174.             if (window ~= $nil)
  175.                 SetWTitle(window, $untitled-name);
  176.                 let viewer = Q3ViewerNew(window, window.portRect, $kQ3ViewerDefault); 
  177.                 let document = make(<Viewer-Document>, window: window, viewer: viewer);
  178.                 viewer-documents[window] := document;
  179.                 ShowWindow(window);
  180.             end if;
  181.         end method;
  182.         
  183.         local method OpenViewer ()
  184.             if (StandardGetFile(reply))
  185.                 let window = GetNewCWindow($Document-Window-ID);
  186.                 if (window ~= $nil)
  187.                     let spec = reply.sfFile;
  188.                     SetWTitle(window, spec.name);
  189.                     let viewer = Q3ViewerNew(window, window.portRect, $kQ3ViewerDefault); 
  190.                     let document = make(<Viewer-Document>, window: window, viewer: viewer);
  191.                     viewer-documents[window] := document;
  192.                     // open the file.
  193.                     let (result, refNum) = FSpOpenDF(reply.sfFile, $fsRdPerm);
  194.                     if (result = $noErr)
  195.                         Q3ViewerUseFile(viewer, refNum);
  196.                         FSClose(refNum);
  197.                     end if;
  198.                     ShowWindow(window);
  199.                 end if;
  200.             end if;
  201.         end method;
  202.         
  203.         local method CloseViewer (window :: <WindowPtr>)
  204.             let document = viewer-documents[window];
  205.             viewer-documents := remove-key!(viewer-documents, window);
  206.             Q3ViewerDispose(document.viewer-object);
  207.             DisposeWindow(window);
  208.         end method;
  209.         
  210.         local method DoAbout ()
  211.             let sound = GetResource(os-type("snd "), $Cricket-snd-ID);
  212.             if (sound ~= $nil)
  213.                 SndPlay($nil, sound, #f);
  214.                 ReleaseResource(sound);
  215.             end if;
  216.             Alert($About-Alert-ID);
  217.         end method;
  218.         
  219.         // pre-process menu states.
  220.         local method UpdateMenus ()
  221.             let fileMenu = GetMenuHandle($File-Menu-ID);
  222.             let editMenu = GetMenuHandle($Edit-Menu-ID);
  223.             let fontMenu = GetMenuHandle($Font-Menu-ID);
  224.             if (FrontWindow() ~= $nil)
  225.                 EnableItem(fileMenu, $Close-Item);
  226.                 EnableItem(editMenu, 0);
  227.                 EnableItem(fontMenu, 0);
  228.             else
  229.                 DisableItem(fileMenu, $Close-Item);
  230.                 DisableItem(editMenu, 0);
  231.                 DisableItem(fontMenu, 0);
  232.             end if;
  233.             DrawMenuBar();
  234.         end method;
  235.         
  236.         // process menu selections.
  237.         local method DoMenu (menu, item)
  238.             if (menu ~= 0 & item ~= 0)
  239.                 select (menu by \=)
  240.                 $Apple-Menu-ID =>
  241.                     if (item = $About-Item)
  242.                         DoAbout();
  243.                     else
  244.                         GetMenuItemText(GetMenuHandle($Apple-Menu-ID), item, itemString);
  245.                         OpenDeskAcc(itemString);
  246.                     end if;
  247.                 $File-Menu-ID =>
  248.                     select (item by \=)
  249.                     $New-Item =>
  250.                         NewViewer();
  251.                     $Open-Item =>
  252.                         OpenViewer();
  253.                     $Close-Item =>
  254.                         let window = FrontWindow();
  255.                         if (window ~= $nil)
  256.                             CloseViewer(window);
  257.                         end if;
  258.                     $Quit-Item =>
  259.                         return();
  260.                     end select;
  261.                 $Font-Menu-ID =>
  262.                     let window = FrontWindow();
  263.                     if (window ~= $nil)
  264.                         GetMenuItemText(GetMenuHandle($Font-Menu-ID), item, itemString);
  265.                         SetPort(window);
  266.                         TextFont(GetFNum(itemString));
  267.                         DrawViewer(window);
  268.                     end if;
  269.                 $Edit-Menu-ID =>
  270.                     let (frontWindow, frontViewer) = FrontDocument();
  271.                     if (frontViewer ~= $nil)
  272.                         select (item by \=)
  273.                         $Cut-Item =>
  274.                             Q3ViewerCut(frontViewer);
  275.                         $Copy-Item =>
  276.                             Q3ViewerCopy(frontViewer);
  277.                         $Paste-Item =>
  278.                             Q3ViewerPaste(frontViewer);
  279.                         $Clear-Item =>
  280.                             Q3ViewerClear(frontViewer);
  281.                         end select;
  282.                     end if;
  283.                 otherwise =>
  284.                     GetMenuItemText(GetMenuHandle(menu), item, itemString);
  285.                     DebugStr(itemString);
  286.                 end select;
  287.             end if;
  288.             HiliteMenu(0);
  289.             UpdateMenus();
  290.         end method;
  291.         
  292.         // process mouse clicks.
  293.         local method DoClick (event :: <EventRecord>)
  294.             let (partCode, window) = FindWindow(event-where(event));
  295.             select (partCode)
  296.             $inMenuBar =>
  297.                 UpdateMenus();
  298.                 let (menu, item) = MenuSelect(event-where(event));
  299.                 DoMenu(menu, item);
  300.             $inDesk =>
  301.                 #f;
  302.             $inDrag =>
  303.                 DragWindow(window, event-where(event));
  304.             $inContent =>
  305.                 if (window ~= FrontWindow())
  306.                     SelectWindow(window);
  307.                 end if;
  308.             $inGoAway =>
  309.                 if (TrackGoAway(window, event-where(event)))
  310.                     CloseViewer(window);
  311.                     UpdateMenus();
  312.                 end if;
  313.             $inZoomIn, $inZoomOut =>
  314.                 if (TrackBox(window, event-where(event), partCode))
  315.                     SetPort(window);
  316.                     EraseRect(window.portRect);
  317.                     ZoomWindow(window, partCode, #t);
  318.                     Q3ViewerSetBounds(viewer-documents[window].viewer-object, window.portRect);
  319.                 end if;
  320.             $inGrow =>
  321.                 let (height, width) = GrowWindow(window, event-where(event), sizeRect);
  322.                 if (height ~= 0 & width ~= 0)
  323.                     SetPort(window);
  324.                     SizeWindow(window, width, height, #f);
  325.                     EraseRect(window.portRect);
  326.                     DrawViewer(window);
  327.                 end if;
  328.             otherwise =>
  329.                 #f;
  330.             end select;
  331.         end method;
  332.         
  333.         local method DoRotation (document :: <Viewer-Document>, forward :: <boolean>)
  334.             // mess with the transformation matrix.
  335.             let view = Q3ViewerGetView(document.viewer-object);
  336.             let matrix = document.viewer-matrix;
  337.             
  338.             // multiply the matrix.
  339.             Q3Matrix4x4-SetRotate-XYZ(tempMatrix, 0.1, 0.12, 0.08);
  340.             Q3Matrix4x4-Multiply(matrix, tempMatrix, matrix);
  341.             
  342.             // re-render the view.
  343.             SetPort(document.viewer-window);
  344.             Q3ViewerDraw(document.viewer-object);
  345.  
  346.             Q3View-StartRendering(view);
  347.             let renderStatus = $kQ3ViewStatusRetraverse;
  348.             while (renderStatus = $kQ3ViewStatusRetraverse)
  349.                 Q3MatrixTransform-Submit(matrix, view);
  350.                 renderStatus := Q3View-EndRendering(view);
  351.             end while;
  352.         end method;
  353.         
  354.         // process keystrokes.
  355.         local method DoKey (event :: <EventRecord>)
  356.             let ch = as(<character>, logand(event-message(event), 255));
  357.             if (logand(event-modifiers(event), $cmdKey) = $cmdKey)
  358.                 UpdateMenus();
  359.                 let (menu, item) = MenuKey(ch);
  360.                 DoMenu(menu, item);
  361.             else
  362.                 let (frontWindow, frontViewer, frontDocument) = FrontDocument();
  363.                 if (frontDocument)
  364.                     select (ch)
  365.                     '+' =>
  366.                         DoRotation(frontDocument, #t);
  367.                     '-' =>
  368.                         DoRotation(frontDocument, #f);
  369.                     otherwise =>
  370.                         #f;
  371.                     end select;
  372.                 end if;
  373.             end if;
  374.         end method;
  375.         
  376.         // process update events.
  377.         local method DoUpdate (event :: <EventRecord>)
  378.             let window = as(<WindowPtr>, event-message(event));
  379.             BeginUpdate(window);
  380.             DrawViewer(window);
  381.             EndUpdate(window);
  382.         end method;
  383.         
  384.         // process activate events.
  385.         local method DoActivate (event :: <EventRecord>)
  386.             let window = as(<WindowPtr>, event-message(event));
  387.             DrawViewer(window);
  388.         end method;
  389.         
  390.         // get initial state right.
  391.         UpdateMenus();
  392.         
  393.         // the event loop goes on until somebody quits.
  394.         while (signed-long-at(theTimeToQuit) = 0)
  395.             let (frontWindow, frontViewer) = FrontDocument();
  396.             if (frontViewer ~= $nil)
  397.                 SetPort(frontWindow);
  398.                 GetMouse(localWhere);
  399.                 if (PtInRect(localWhere, frontWindow.portRect))
  400.                     Q3ViewerAdjustCursor(frontViewer, localWhere);
  401.                 else
  402.                     SetCursor(qd.arrow);
  403.                 end if;
  404.             end if;
  405.             if (WaitNextEvent($everyEvent, event, 5, mouseRgn))
  406.                 let what = event-what(event);
  407.                 let eventHandled =
  408.                     if (frontViewer ~= $nil & what ~= $updateEvt)
  409.                         Q3ViewerEvent(frontViewer, event);
  410.                     else
  411.                         #f;
  412.                     end if;
  413.                 if (~eventHandled)
  414.                     select (event-what(event))
  415.                     $mouseDown =>
  416.                         DoClick(event);
  417.                     $keyDown =>
  418.                         DoKey(event);
  419.                     $updateEvt =>
  420.                         DoUpdate(event);
  421.                     $activateEvt =>
  422.                         DoActivate(event);
  423.                     $osEvt =>
  424.                         SysBeep(1);
  425.                     $kHighLevelEvent =>
  426.                         let result = AEProcessAppleEvent(event);
  427.                     otherwise =>
  428.                         #f;
  429.                     end select;
  430.                 end if;
  431.             end if;
  432.         end while;
  433.     cleanup
  434.         destroy(event);
  435.         destroy(itemString);
  436.         DisposeRgn(mouseRgn);
  437.         DisposeRgn(oldClip);
  438.         DisposeRgn(newClip);
  439.         destroy(textRect);
  440.         destroy(sizeRect);
  441.         destroy(reply);
  442.         DisposePtr(as(<Ptr>, tempMatrix));
  443.         for (document in viewer-documents)
  444.             Q3ViewerDispose(document.viewer-object);
  445.             DisposeWindow(document.viewer-window);
  446.             destroy(document.viewer-matrix);
  447.         end for;
  448.         /* kill-thread(collector-thread); */
  449.     end block;
  450. end method EventLoop;
  451.